using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using Godot;
using System.Data;

public class PistonBlock : BlockMaterial
{
    const int length = 12;
    public PistonBlock() : base("piston")
    {
        DisPlayName = "活塞";
        Collide = true;
        Durable = 1.0f;
        RotateMax = 4;
        StateMax = 12;
        base.BreakEvent = this.OnBreak;
        TickEvent = Tick;
    }
    public bool CanPush(List<BlockData> blocks)
    {
        if (blocks == null) return false;
        for (int i = 0; i < blocks.Count; i++)
        {
            if (blocks[i].blockEntity != null)
            {
                return false;
            }
            if ((blocks[i].GetMaterial() is PistonBlock) && blocks[i].State > 0)
            {
                return false;
            }
        }
        return true;
    }
    public bool PushBlocks(BlockWorld world, BlockData block)
    {

        List<BlockData> blocks = GetAngleBlocks(world, block);
        if (CanPush(blocks))
        {
            if (block.Rotate == 0)
                for (int i = 2; i < length; i++)
                    if (i - 2 < blocks.Count) world.SetBlock(block.position.X, block.position.Y + i, block.position.Z, blocks[i - 2].GetMaterial());
            if (block.Rotate == 1)
                for (int i = 2; i < length; i++)
                    if (i - 2 < blocks.Count) world.SetBlock(block.position.X + i, block.position.Y, block.position.Z, blocks[i - 2].GetMaterial());
            if (block.Rotate == 2)
                for (int i = 2; i < length; i++)
                    if (i - 2 < blocks.Count) world.SetBlock(block.position.X, block.position.Y - i, block.position.Z, blocks[i - 2].GetMaterial());
            if (block.Rotate == 3)
                for (int i = 2; i < length; i++)
                    if (i - 2 < blocks.Count) world.SetBlock(block.position.X - i, block.position.Y, block.position.Z, blocks[i - 2].GetMaterial());
            GD.Print("push done");
            return true;
        }
        return false;

    }
    public List<BlockData> GetAngleBlocks(BlockWorld world, BlockData block)
    {
        int angle = block.Rotate;
        List<BlockData> result = new List<BlockData>();
        if (angle == 0)
        {
            for (int i = 1; i < length; i++)
            {
                BlockData bd = world.GetBlock(block.position.X, block.position.Y + i, block.position.Z);
                if (bd == null) return null;
                result.Add(bd);
                if (bd.Name == "air") return result;
            }
            return result;
        }
        else
        if (angle == 1)
        {
            for (int i = 1; i < length; i++)
            {
                BlockData bd = world.GetBlock(block.position.X + i, block.position.Y, block.position.Z);
                if (bd == null) return null;
                result.Add(bd);
                if (bd.Name == "air") return result;
            }
            return result;
        }
        else
        if (angle == 2)
        {
            for (int i = 1; i < length; i++)
            {
                BlockData bd = world.GetBlock(block.position.X, block.position.Y - i, block.position.Z);
                if (bd == null) return null;
                result.Add(bd);
                if (bd.Name == "air") return result;
            }
            return result;
        }
        else
        if (angle == 3)
        {
            for (int i = 1; i < length; i++)
            {
                BlockData bd = world.GetBlock(block.position.X - i, block.position.Y, block.position.Z);
                if (bd == null) return null;
                result.Add(bd);
                if (bd.Name == "air") return result;
            }
            return result;
        }
        return null;
    }
    private bool OnBreak(PlayerBreakBlockEvent e)
    {
        if (e.block.State == 2)
        {
            BlockData back = e.GetBackBlock();
            if (back != null && back.Name == "piston" && back.Rotate == e.block.Rotate)
            {
                back.SetBlock(Materials.Air);
            }
        }
        else
        {
            BlockData font = e.GetFontBlock();
            if (font != null && font.Name == "piston" && font.Rotate == e.block.Rotate && font.State == 2)
            {
                font.SetBlock(Materials.Air);
            }
        }
        return true;
    }
    public void Tick(UpdataTickEvent e)
    {
        if (e.block.State == 2)
        {
            BlockData back = e.GetBackBlock();
            if (back != null && (back.Name != "piston" || back.Rotate != e.block.Rotate || back.power <= 0))
            {
                e.block.SetBlock(Materials.Air);
            }
            else
            {

            }
            return;
        }
        if (e.block.power > 0)
        {
            BlockData font = e.GetFontBlock();
            if (e.block.State == 1 || e.block.State == 0)
            {
                if (font != null && font.Name == "air")
                {
                    PushBlocks(e.world, e.block);

                    font.SetBlock(Materials.Piston, 2);
                    font.Rotate = e.block.Rotate;
                    e.block.SetState(1);
                }
            }
            if (e.block.State == 0)
            {
                if (font != null && font.Name != "piston")
                {
                    e.block.SetState(0);
                }
            }
        }
        else
        {
            e.block.SetState(0);
        }
    }
    public override int GetTileId(BlockData block)
    {
        return id + block.Rotate * 3 + block.State;
    }
}